<template>
  <div class="pdf-container">
    <div class="pdf-viewer">
      <div class="progress" v-if="!pageCount">
        <div class="indeterminate"></div>
      </div>
      <header class="pdf-viewer__header box-shadow" v-if="pageCount">
        <div class="pdf-preview-toggle">
          <a @click.prevent.stop="togglePreview" class="icon">
            <PreviewIcon />
          </a>
        </div>

        <PDFZoom :scale="scale" @change="updateScale" @fit="updateFit" class="header-item" />

        <PDFPaginator v-model="currentPage" :pageCount="pageCount" class="header-item" />

        <slot name="header"></slot>
      </header>

      <PDFData
        class="pdf-viewer__main"
        :url="url"
        @page-count="updatePageCount"
        @page-focus="updateCurrentPage"
        @document-rendered="onDocumentRendered"
        @document-errored="onDocumentErrored"
      >
        <template v-slot:preview="{pages}">
          <PDFPreview
            v-show="isPreviewEnabled"
            class="pdf-viewer__preview"
            v-bind="{pages, scale, currentPage, pageCount, isPreviewEnabled}"
          />
        </template>

        <template v-slot:document="{pages}">
          <PDFDocument
            class="pdf-viewer__document"
            :class="{ 'preview-enabled': isPreviewEnabled }"
            v-bind="{pages, scale, optimalScale, fit, currentPage, pageCount, isPreviewEnabled}"
            @scale-change="updateScale"
          />
        </template>
      </PDFData>
    </div>
  </div>
</template>

<script>
import PreviewIcon from "@/assets/pdf-view/icon-preview.svg";

import PDFDocument from "./PDFDocument";
import PDFData from "./PDFData";
import PDFPaginator from "./PDFPaginator";
import PDFPreview from "./PDFPreview";
import PDFZoom from "./PDFZoom";

function floor(value, precision) {
  const multiplier = Math.pow(10, precision || 0);
  return Math.floor(value * multiplier) / multiplier;
}

export default {
  name: "PDFViewer",

  components: {
    PDFDocument,
    PDFData,
    PDFPaginator,
    PDFPreview,
    PDFZoom,
    PreviewIcon
  },

  props: {
    url: String
  },

  data() {
    return {
      scale: undefined,
      optimalScale: undefined,
      fit: undefined,
      currentPage: 1,
      pageCount: undefined,
      isPreviewEnabled: false
    };
  },

  methods: {
    onDocumentRendered() {
      this.$emit("document-errored", this.url);
    },

    onDocumentErrored(e) {
      this.$emit("document-errored", e);
    },

    updateScale({ scale, isOptimal = false }) {
      const roundedScale = floor(scale, 2);
      if (isOptimal) this.optimalScale = roundedScale;
      this.scale = roundedScale;
    },

    updateFit(fit) {
      this.fit = fit;
    },

    updatePageCount(pageCount) {
      this.pageCount = pageCount;
    },

    updateCurrentPage(pageNumber) {
      this.currentPage = pageNumber;
    },

    togglePreview() {
      this.isPreviewEnabled = !this.isPreviewEnabled;
    }
  },

  watch: {
    url() {
      this.currentPage = undefined;
    }
  },

  mounted() {
    document.body.classList.add("overflow-hidden");
  }
};
</script>

<style scoped>
header {
  display: flex;
  justify-content: center;
  align-items: center;
  flex-wrap: wrap;
  padding: 1em;
  position: relative;
  z-index: 99;
}
.header-item {
  margin: 0 2.5em;
}

.pdf-viewer .pdf-viewer__document,
.pdf-viewer .pdf-viewer__preview {
  top: 70px;
}

.pdf-viewer__preview {
  display: block;
  width: 15%;
  right: 85%;
}

.pdf-viewer__document {
  top: 70px;
  width: 100%;
  left: 0;
}

.pdf-viewer__document.preview-enabled {
  width: 85%;
  left: 15%;
}

.pdf-container {
  width: 100%;
  height: 650px;
  max-height: 650px;
  position: relative;
  background: rgb(30, 30, 30);
}
a.icon {
  cursor: pointer;
  display: block;
  color: #ffffff;
  font-weight: bold;
  padding: 0.25em;
  width: 1em;
  height: 1.5em;
  font-size: 1.5em;
}
@media print {
  header {
    display: none;
  }
}

/* Progress Bar */
.progress {
  position: relative;
  height: 10px;
  display: block;
  width: 100%;
  background-color: #FFFFFF;
  background-clip: padding-box;
  overflow: hidden;
}
.progress .indeterminate {
  background-color: #ffc841;
}
.progress .indeterminate:before {
  content: "";
  position: absolute;
  background-color: inherit;
  top: 0;
  left: 0;
  bottom: 0;
  will-change: left, right;
  -webkit-animation: indeterminate 1.1s cubic-bezier(0.65, 0.815, 0.735, 0.395)
    infinite;
  animation: indeterminate 1.1s cubic-bezier(0.65, 0.815, 0.735, 0.395) infinite;
}
.progress .indeterminate:after {
  content: "";
  position: absolute;
  background-color: inherit;
  top: 0;
  left: 0;
  bottom: 0;
  will-change: left, right;
  -webkit-animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
    infinite;
  animation: indeterminate-short 2.1s cubic-bezier(0.165, 0.84, 0.44, 1)
    infinite;
  -webkit-animation-delay: 1.15s;
  animation-delay: 1.15s;
}

@-webkit-keyframes indeterminate {
  0% {
    left: -35%;
    right: 100%;
  }
  60% {
    left: 100%;
    right: -90%;
  }
  100% {
    left: 100%;
    right: -90%;
  }
}
@keyframes indeterminate {
  0% {
    left: -35%;
    right: 100%;
  }
  60% {
    left: 100%;
    right: -90%;
  }
  100% {
    left: 100%;
    right: -90%;
  }
}
@-webkit-keyframes indeterminate-short {
  0% {
    left: -200%;
    right: 100%;
  }
  60% {
    left: 107%;
    right: -8%;
  }
  100% {
    left: 107%;
    right: -8%;
  }
}
@keyframes indeterminate-short {
  0% {
    left: -200%;
    right: 100%;
  }
  60% {
    left: 107%;
    right: -8%;
  }
  100% {
    left: 107%;
    right: -8%;
  }
}
</style>
